#include "PolygonMesh.hpp"

namespace zzz{
PolygonMesh::PolygonMesh():loaded_(false){}
PolygonMesh::~PolygonMesh(){Clear();}
bool PolygonMesh::Clear()
{
  nor_.clear();
  pos_.clear();
  tex_.clear();
  for (zuint i=0; i<groups_.size(); i++)
    delete groups_[i];
  groups_.clear();
  loaded_=false;
  return true;
}

bool PolygonMesh::Apply(const Translation<float> &offset)
{
  if (!loaded_) return false;
  int len=pos_.size();
  for (int i=0; i<len; i++)
    pos_[i]=offset.Apply(pos_[i]);
  AABB_.SetOffset(offset);
  OriCenter_=offset.Apply(OriCenter_);
  return true;
}

bool PolygonMesh::Apply(const Rotation<float> &t)
{
  if (!loaded_) return false;
  int len=pos_.size();
  for (int i=0; i<len; i++)
    pos_[i]=t.Apply(pos_[i]);
  len=nor_.size();
  for (int i=0; i<len; i++)
  {
    nor_[i]=t.Apply(nor_[i]);
    nor_[i].Normalize();
  }
  AABB_.Reset();
  AABB_+=pos_;
  OriCenter_=AABB_.Center();
  return true;
}

bool PolygonMesh::Apply(const Transformation<float> &t)
{
  if (!loaded_) return false;
  int len=pos_.size();
  for (int i=0; i<len; i++)
    pos_[i]=t.Apply(pos_[i]);
  len=nor_.size();
  for (int i=0; i<len; i++)
  {
    nor_[i]=t.Apply(nor_[i]);
    nor_[i].Normalize();
  }
  AABB_.Reset();
  AABB_+=pos_;
  OriCenter_=AABB_.Center();
  return true;
}

bool PolygonMesh::Scale(float coef)
{
  if (!loaded_) return false;
  for (zuint i=0; i<pos_.size(); i++)
    pos_[i]*=coef;
  AABB_.Min()*=coef;
  AABB_.Max()*=coef;
  Diameter_*=coef;
  return true;
}

bool PolygonMesh::MakeCenter(){return Apply(Translation<float>(-OriCenter_));}

bool PolygonMesh::Normalize(){return Scale(1.0/Diameter_);}


//simple draw and vbo draw
bool PolygonMesh::Draw(int bt)
{
  if (!loaded_) return false;
  for (zuint i=0; i<groups_.size(); i++)
    if (!Draw(i,bt)) return false;
  return true;
}

bool PolygonMesh::Draw(int idx, int bt)
{
  PolygonMeshGroup *g=groups_[idx];
  vector<vector<int> > &facep=g->facep_, &facen=g->facen_, &facet=g->facet_;
  for (zuint i=0; i<facep.size(); i++) 
  {
    glBegin(GL_POLYGON);
    int cur=0;
    for (zuint j=0; j<facep[i].size(); j++)
    {
      if (CheckBit(bt, MESH_NOR)) glNormal3fv(nor_[facen[i][j]].Data());
      if (CheckBit(bt, MESH_TEX)) glTexCoord3fv(tex_[facet[i][j]].Data());
      if (CheckBit(bt, MESH_COLOR)) glColor3fv(color_[facep[i][j]].Data());
      if (CheckBit(bt, MESH_POS)) glVertex3fv(pos_[facep[i][j]].Data());
    }
    glEnd();
  }
  return true;
}

bool PolygonMesh::Draw(const string &name, int bt)
{
  for (zuint i=0; i<groups_.size(); i++)
    if (groups_[i]->name_==name) return Draw(i,bt);
  return false;
}


}


